#pragma once

#include <cstddef>
#include <cstring>
#include <stdexcept>

class SimpleString {
  size_t maxSize_;
  char *buffer_;
  size_t length_;

public:
  SimpleString(size_t maxSize) : maxSize_{maxSize}, length_{0} {
    if (maxSize == 0) {
      throw std::runtime_error("maxSize cannot be 0");
    }
    buffer_ = new char[maxSize]{0};
    buffer_[0] = 0;
  }
  SimpleString(const SimpleString &other)
      : maxSize_{other.maxSize_}, buffer_{new char[other.maxSize_]{0}},
        length_{other.length_} {
    std::strncpy(buffer_, other.buffer_, maxSize_);
  }
  SimpleString &operator=(const SimpleString &other) {
    if (this == &other) {
      return *this;
    }
    delete[] buffer_;
    buffer_ = new char[other.maxSize_]{0};
    maxSize_ = other.maxSize_;
    length_ = other.length_;
    std::strncpy(buffer_, other.buffer_, maxSize_);
    return *this;
  }
  SimpleString(SimpleString &&other) noexcept
      : maxSize_{other.maxSize_}, buffer_{other.buffer_},
        length_{other.length_} {
    other.maxSize_ = 0;
    other.buffer_ = nullptr;
    other.length_ = 0;
  }
  SimpleString &operator=(SimpleString &&other) noexcept {
    if (this == &other) {
      return *this;
    }
    delete[] buffer_;
    maxSize_ = other.maxSize_;
    buffer_ = other.buffer_;
    length_ = other.length_;
    other.maxSize_ = 0;
    other.buffer_ = nullptr;
    other.length_ = 0;
    return *this;
  }
  ~SimpleString() { delete[] buffer_; }

public:
  void print(const char *tag) const { printf("%s: %s\n", tag, buffer_); }
  bool appendLine(const char *line) {
    const auto lineLength = strlen(line);
    if (length_ + lineLength + 2 > maxSize_) {
      return false;
    }
    std::strncpy(buffer_ + length_, line, maxSize_ - length_);
    length_ += lineLength;
    buffer_[length_++] = '\n';
    buffer_[length_] = 0;
    return true;
  }
};
